package com.rtsapp.server.benchmark.runner;

import com.rtsapp.server.benchmark.ITestCaseConfig;
import com.rtsapp.server.benchmark.ITestRunnerListener;
import io.netty.channel.EventLoopGroup;
import com.rtsapp.server.logger.Logger;

import java.net.SocketAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * 一个用户的测试用例
 *   一个用户可能有多个测试用例文件需要执行
 *   一个文件对应一次登录后的操作, 游戏也将执行多次登录操作
 */
public class TestSession {

    private static final Logger LOGGER =com.rtsapp.server.logger.LoggerFactory.getLogger( TestSession.class );


    /**
     * 所属的TestRunner
     */
    private final TestRunner runner;


    /**
     * 监听器
     */
    private final ITestRunnerListener listener;

    /**
     * 会话所在的事件循环
     */
    private final EventLoopGroup eventLoop;


    /**
     * 会话ID
     */
    private final int sessionId;

    /**
     * 该会话的上下文
     */
    private final Map<String,Object> context =  new HashMap<>();

    /**
     * 所有需要执行的测试用例文件
     */
    private final ITestCaseConfig[] caseCfgs;


    /**
     * 服务器地址
     */
    private final SocketAddress remotePeer;

    /**
     * 第一次启动的延迟
     */
    private final long initDelay;

    /**
     * 当前执行的测试用例文件的索引
     */
    private int currentCaseCfgIndex = -1 ;


    public TestSession(  TestRunner runner, ITestRunnerListener listener, EventLoopGroup eventLoop, int sessionId, ITestCaseConfig[] caseCfgs, SocketAddress remotePeer, long initDelay ) {
        this.runner = runner;
        this.listener = listener;
        this.eventLoop = eventLoop;
        this.sessionId = sessionId;
        this.caseCfgs = caseCfgs;
        this.remotePeer = remotePeer;
        this.initDelay = initDelay;
    }

    /**
     * 会话启动
     */
    public void start( ){
        LOGGER.info( "[{}]: session({}): 启动", ContextUtils.getContextId( this.getContext()),  sessionId   );
        startNextCaseCfg();
    }


    /**
     * 会话结束啦
     */
    private void complete(){
        LOGGER.info( "[{}]: session({}): 执行完毕", ContextUtils.getContextId( this.getContext()),  sessionId   );
        runner.onSessionClose( this );
    }


    private void startNextCaseCfg( ){

        currentCaseCfgIndex++;

        // 如果测试用例文件已经结束, 该测试会话结束
        // 否则启动连接进行测试
        if( currentCaseCfgIndex >= caseCfgs.length ){
            complete();
        }else {
            startConnection();
        }
    }


    private void startConnection(){

        LOGGER.info( "[{}]: session({}): 第{}次连接{}毫秒后启动" , ContextUtils.getContextId( context ), sessionId, ( currentCaseCfgIndex + 1 ), initDelay );

        TestConnection connection = new TestConnection( this, eventLoop, remotePeer, caseCfgs[ currentCaseCfgIndex ] , runner.getCommandCaseHandlerFactory(), runner.getKeyRSA() );
        connection.start(initDelay);
    }

    public void onConnectionConnected( TestConnection con ){
        LOGGER.info( "[{}]: session({}): 第{}次连接成功" , ContextUtils.getContextId( context ), sessionId, ( currentCaseCfgIndex + 1 ) );

//        LOGGER.info( "session(" + sessionId + "): 第" + ( currentCaseCfgIndex + 1 ) + "次连接成功" );
        listener.onConnectionStart(sessionId, context);
    }

    public void onConnectionClosed( TestConnection con ){
        LOGGER.info( "[{}]: session({}): 第{}次连接关闭",  ContextUtils.getContextId( context ), sessionId, ( currentCaseCfgIndex + 1 ) );
//        LOGGER.info( "session(" + sessionId + "): 第" + ( currentCaseCfgIndex + 1 ) + "次连接关闭" );

        startNextCaseCfg();
    }

    public Map<String, Object> getContext() {
        return context;
    }

    public int getSessionId() {
        return sessionId;
    }
}